<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        background: #000;
      }

      canvas {
        display: block;
      }

      #gui {
        left: 0;
        position: fixed;
        top: 0;
      }
    </style>
  </head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script>
    var dat = dat || {};
    dat.gui = dat.gui || {};
    dat.utils = dat.utils || {};
    dat.controllers = dat.controllers || {};
    dat.dom = dat.dom || {};
    dat.color = dat.color || {};
    dat.utils.css = (function () {
      return {
        load: function (e, a) {
          var a = a || document,
            c = a.createElement("link");
          c.type = "text/css";
          c.rel = "stylesheet";
          c.href = e;
          a.getElementsByTagName("head")[0].appendChild(c);
        },
        inject: function (e, a) {
          var a = a || document,
            c = document.createElement("style");
          c.type = "text/css";
          c.innerHTML = e;
          a.getElementsByTagName("head")[0].appendChild(c);
        },
      };
    })();
    dat.utils.common = (function () {
      var e = Array.prototype.forEach,
        a = Array.prototype.slice;
      return {
        BREAK: {},
        extend: function (c) {
          this.each(
            a.call(arguments, 1),
            function (a) {
              for (var f in a) this.isUndefined(a[f]) || (c[f] = a[f]);
            },
            this
          );
          return c;
        },
        defaults: function (c) {
          this.each(
            a.call(arguments, 1),
            function (a) {
              for (var f in a) this.isUndefined(c[f]) && (c[f] = a[f]);
            },
            this
          );
          return c;
        },
        compose: function () {
          var c = a.call(arguments);
          return function () {
            for (var d = a.call(arguments), f = c.length - 1; f >= 0; f--)
              d = [c[f].apply(this, d)];
            return d[0];
          };
        },
        each: function (a, d, f) {
          if (e && a.forEach === e) a.forEach(d, f);
          else if (a.length === a.length + 0)
            for (var b = 0, n = a.length; b < n; b++) {
              if (b in a && d.call(f, a[b], b) === this.BREAK) break;
            }
          else for (b in a) if (d.call(f, a[b], b) === this.BREAK) break;
        },
        defer: function (a) {
          setTimeout(a, 0);
        },
        toArray: function (c) {
          return c.toArray ? c.toArray() : a.call(c);
        },
        isUndefined: function (a) {
          return a === void 0;
        },
        isNull: function (a) {
          return a === null;
        },
        isNaN: function (a) {
          return a !== a;
        },
        isArray:
          Array.isArray ||
          function (a) {
            return a.constructor === Array;
          },
        isObject: function (a) {
          return a === Object(a);
        },
        isNumber: function (a) {
          return a === a + 0;
        },
        isString: function (a) {
          return a === a + "";
        },
        isBoolean: function (a) {
          return a === false || a === true;
        },
        isFunction: function (a) {
          return Object.prototype.toString.call(a) === "[object Function]";
        },
      };
    })();
    dat.controllers.Controller = (function (e) {
      var a = function (a, d) {
        this.initialValue = a[d];
        this.domElement = document.createElement("div");
        this.object = a;
        this.property = d;
        this.__onFinishChange = this.__onChange = void 0;
      };
      e.extend(a.prototype, {
        onChange: function (a) {
          this.__onChange = a;
          return this;
        },
        onFinishChange: function (a) {
          this.__onFinishChange = a;
          return this;
        },
        setValue: function (a) {
          this.object[this.property] = a;
          this.__onChange && this.__onChange.call(this, a);
          this.updateDisplay();
          return this;
        },
        getValue: function () {
          return this.object[this.property];
        },
        updateDisplay: function () {
          return this;
        },
        isModified: function () {
          return this.initialValue !== this.getValue();
        },
      });
      return a;
    })(dat.utils.common);
    dat.dom.dom = (function (e) {
      function a(b) {
        if (b === "0" || e.isUndefined(b)) return 0;
        b = b.match(d);
        return !e.isNull(b) ? parseFloat(b[1]) : 0;
      }
      var c = {};
      e.each(
        {
          HTMLEvents: ["change"],
          MouseEvents: [
            "click",
            "mousemove",
            "mousedown",
            "mouseup",
            "mouseover",
          ],
          KeyboardEvents: ["keydown"],
        },
        function (b, a) {
          e.each(b, function (b) {
            c[b] = a;
          });
        }
      );
      var d = /(\d+(\.\d+)?)px/,
        f = {
          makeSelectable: function (b, a) {
            if (!(b === void 0 || b.style === void 0))
              (b.onselectstart = a
                ? function () {
                    return false;
                  }
                : function () {}),
                (b.style.MozUserSelect = a ? "auto" : "none"),
                (b.style.KhtmlUserSelect = a ? "auto" : "none"),
                (b.unselectable = a ? "on" : "off");
          },
          makeFullscreen: function (b, a, d) {
            e.isUndefined(a) && (a = true);
            e.isUndefined(d) && (d = true);
            b.style.position = "absolute";
            if (a) (b.style.left = 0), (b.style.right = 0);
            if (d) (b.style.top = 0), (b.style.bottom = 0);
          },
          fakeEvent: function (b, a, d, f) {
            var d = d || {},
              m = c[a];
            if (!m) throw Error("Event type " + a + " not supported.");
            var l = document.createEvent(m);
            switch (m) {
              case "MouseEvents":
                l.initMouseEvent(
                  a,
                  d.bubbles || false,
                  d.cancelable || true,
                  window,
                  d.clickCount || 1,
                  0,
                  0,
                  d.x || d.clientX || 0,
                  d.y || d.clientY || 0,
                  false,
                  false,
                  false,
                  false,
                  0,
                  null
                );
                break;
              case "KeyboardEvents":
                m = l.initKeyboardEvent || l.initKeyEvent;
                e.defaults(d, {
                  cancelable: true,
                  ctrlKey: false,
                  altKey: false,
                  shiftKey: false,
                  metaKey: false,
                  keyCode: void 0,
                  charCode: void 0,
                });
                m(
                  a,
                  d.bubbles || false,
                  d.cancelable,
                  window,
                  d.ctrlKey,
                  d.altKey,
                  d.shiftKey,
                  d.metaKey,
                  d.keyCode,
                  d.charCode
                );
                break;
              default:
                l.initEvent(a, d.bubbles || false, d.cancelable || true);
            }
            e.defaults(l, f);
            b.dispatchEvent(l);
          },
          bind: function (b, a, d, c) {
            b.addEventListener
              ? b.addEventListener(a, d, c || false)
              : b.attachEvent && b.attachEvent("on" + a, d);
            return f;
          },
          unbind: function (b, a, d, c) {
            b.removeEventListener
              ? b.removeEventListener(a, d, c || false)
              : b.detachEvent && b.detachEvent("on" + a, d);
            return f;
          },
          addClass: function (b, a) {
            if (b.className === void 0) b.className = a;
            else if (b.className !== a) {
              var d = b.className.split(/ +/);
              if (d.indexOf(a) == -1)
                d.push(a),
                  (b.className = d
                    .join(" ")
                    .replace(/^\s+/, "")
                    .replace(/\s+$/, ""));
            }
            return f;
          },
          removeClass: function (b, a) {
            if (a) {
              if (b.className !== void 0)
                if (b.className === a) b.removeAttribute("class");
                else {
                  var d = b.className.split(/ +/),
                    c = d.indexOf(a);
                  if (c != -1) d.splice(c, 1), (b.className = d.join(" "));
                }
            } else b.className = void 0;
            return f;
          },
          hasClass: function (a, d) {
            return (
              RegExp("(?:^|\\s+)" + d + "(?:\\s+|$)").test(a.className) || false
            );
          },
          getWidth: function (b) {
            b = getComputedStyle(b);
            return (
              a(b["border-left-width"]) +
              a(b["border-right-width"]) +
              a(b["padding-left"]) +
              a(b["padding-right"]) +
              a(b.width)
            );
          },
          getHeight: function (b) {
            b = getComputedStyle(b);
            return (
              a(b["border-top-width"]) +
              a(b["border-bottom-width"]) +
              a(b["padding-top"]) +
              a(b["padding-bottom"]) +
              a(b.height)
            );
          },
          getOffset: function (a) {
            var d = {
              left: 0,
              top: 0,
            };
            if (a.offsetParent) {
              do (d.left += a.offsetLeft), (d.top += a.offsetTop);
              while ((a = a.offsetParent));
            }
            return d;
          },
          isActive: function (a) {
            return a === document.activeElement && (a.type || a.href);
          },
        };
      return f;
    })(dat.utils.common);
    dat.controllers.OptionController = (function (e, a, c) {
      var d = function (f, b, e) {
        d.superclass.call(this, f, b);
        var h = this;
        this.__select = document.createElement("select");
        if (c.isArray(e)) {
          var j = {};
          c.each(e, function (a) {
            j[a] = a;
          });
          e = j;
        }
        c.each(e, function (a, b) {
          var d = document.createElement("option");
          d.innerHTML = b;
          d.setAttribute("value", a);
          h.__select.appendChild(d);
        });
        this.updateDisplay();
        a.bind(this.__select, "change", function () {
          h.setValue(this.options[this.selectedIndex].value);
        });
        this.domElement.appendChild(this.__select);
      };
      d.superclass = e;
      c.extend(d.prototype, e.prototype, {
        setValue: function (a) {
          a = d.superclass.prototype.setValue.call(this, a);
          this.__onFinishChange &&
            this.__onFinishChange.call(this, this.getValue());
          return a;
        },
        updateDisplay: function () {
          this.__select.value = this.getValue();
          return d.superclass.prototype.updateDisplay.call(this);
        },
      });
      return d;
    })(dat.controllers.Controller, dat.dom.dom, dat.utils.common);
    dat.controllers.NumberController = (function (e, a) {
      var c = function (d, f, b) {
        c.superclass.call(this, d, f);
        b = b || {};
        this.__min = b.min;
        this.__max = b.max;
        this.__step = b.step;
        d = this.__impliedStep = a.isUndefined(this.__step)
          ? this.initialValue == 0
            ? 1
            : Math.pow(
                10,
                Math.floor(Math.log(this.initialValue) / Math.LN10)
              ) / 10
          : this.__step;
        d = d.toString();
        this.__precision =
          d.indexOf(".") > -1 ? d.length - d.indexOf(".") - 1 : 0;
      };
      c.superclass = e;
      a.extend(c.prototype, e.prototype, {
        setValue: function (a) {
          if (this.__min !== void 0 && a < this.__min) a = this.__min;
          else if (this.__max !== void 0 && a > this.__max) a = this.__max;
          this.__step !== void 0 &&
            a % this.__step != 0 &&
            (a = Math.round(a / this.__step) * this.__step);
          return c.superclass.prototype.setValue.call(this, a);
        },
        min: function (a) {
          this.__min = a;
          return this;
        },
        max: function (a) {
          this.__max = a;
          return this;
        },
        step: function (a) {
          this.__step = a;
          return this;
        },
      });
      return c;
    })(dat.controllers.Controller, dat.utils.common);
    dat.controllers.NumberControllerBox = (function (e, a, c) {
      var d = function (f, b, e) {
        function h() {
          var a = parseFloat(l.__input.value);
          c.isNaN(a) || l.setValue(a);
        }
        function j(a) {
          var b = o - a.clientY;
          l.setValue(l.getValue() + b * l.__impliedStep);
          o = a.clientY;
        }
        function m() {
          a.unbind(window, "mousemove", j);
          a.unbind(window, "mouseup", m);
        }
        this.__truncationSuspended = false;
        d.superclass.call(this, f, b, e);
        var l = this,
          o;
        this.__input = document.createElement("input");
        this.__input.setAttribute("type", "text");
        a.bind(this.__input, "change", h);
        a.bind(this.__input, "blur", function () {
          h();
          l.__onFinishChange && l.__onFinishChange.call(l, l.getValue());
        });
        a.bind(this.__input, "mousedown", function (b) {
          a.bind(window, "mousemove", j);
          a.bind(window, "mouseup", m);
          o = b.clientY;
        });
        a.bind(this.__input, "keydown", function (a) {
          if (a.keyCode === 13)
            (l.__truncationSuspended = true),
              this.blur(),
              (l.__truncationSuspended = false);
        });
        this.updateDisplay();
        this.domElement.appendChild(this.__input);
      };
      d.superclass = e;
      c.extend(d.prototype, e.prototype, {
        updateDisplay: function () {
          var a = this.__input,
            b;
          if (this.__truncationSuspended) b = this.getValue();
          else {
            b = this.getValue();
            var c = Math.pow(10, this.__precision);
            b = Math.round(b * c) / c;
          }
          a.value = b;
          return d.superclass.prototype.updateDisplay.call(this);
        },
      });
      return d;
    })(dat.controllers.NumberController, dat.dom.dom, dat.utils.common);
    dat.controllers.NumberControllerSlider = (function (e, a, c, d, f) {
      var b = function (d, c, f, e, l) {
        function o(b) {
          b.preventDefault();
          var d = a.getOffset(g.__background),
            c = a.getWidth(g.__background);
          g.setValue(
            g.__min +
              (g.__max - g.__min) *
                ((b.clientX - d.left) / (d.left + c - d.left))
          );
          return false;
        }
        function y() {
          a.unbind(window, "mousemove", o);
          a.unbind(window, "mouseup", y);
          g.__onFinishChange && g.__onFinishChange.call(g, g.getValue());
        }
        b.superclass.call(this, d, c, {
          min: f,
          max: e,
          step: l,
        });
        var g = this;
        this.__background = document.createElement("div");
        this.__foreground = document.createElement("div");
        a.bind(this.__background, "mousedown", function (b) {
          a.bind(window, "mousemove", o);
          a.bind(window, "mouseup", y);
          o(b);
        });
        a.addClass(this.__background, "slider");
        a.addClass(this.__foreground, "slider-fg");
        this.updateDisplay();
        this.__background.appendChild(this.__foreground);
        this.domElement.appendChild(this.__background);
      };
      b.superclass = e;
      b.useDefaultStyles = function () {
        c.inject(f);
      };
      d.extend(b.prototype, e.prototype, {
        updateDisplay: function () {
          this.__foreground.style.width =
            ((this.getValue() - this.__min) / (this.__max - this.__min)) * 100 +
            "%";
          return b.superclass.prototype.updateDisplay.call(this);
        },
      });
      return b;
    })(
      dat.controllers.NumberController,
      dat.dom.dom,
      dat.utils.css,
      dat.utils.common,
      ".slider {\n  box-shadow: inset 0 2px 4px rgba(0,0,0,0.15);\n  height: 1em;\n  border-radius: 1em;\n  background-color: #eee;\n  padding: 0 0.5em;\n  overflow: hidden;\n}\n\n.slider-fg {\n  padding: 1px 0 2px 0;\n  background-color: #aaa;\n  height: 1em;\n  margin-left: -0.5em;\n  padding-right: 0.5em;\n  border-radius: 1em 0 0 1em;\n}\n\n.slider-fg:after {\n  display: inline-block;\n  border-radius: 1em;\n  background-color: #fff;\n  border:  1px solid #aaa;\n  content: '';\n  float: right;\n  margin-right: -1em;\n  margin-top: -1px;\n  height: 0.9em;\n  width: 0.9em;\n}"
    );
    dat.controllers.FunctionController = (function (e, a, c) {
      var d = function (c, b, e) {
        d.superclass.call(this, c, b);
        var h = this;
        this.__button = document.createElement("div");
        this.__button.innerHTML = e === void 0 ? "Fire" : e;
        a.bind(this.__button, "click", function (a) {
          a.preventDefault();
          h.fire();
          return false;
        });
        a.addClass(this.__button, "button");
        this.domElement.appendChild(this.__button);
      };
      d.superclass = e;
      c.extend(d.prototype, e.prototype, {
        fire: function () {
          this.__onChange && this.__onChange.call(this);
          this.__onFinishChange &&
            this.__onFinishChange.call(this, this.getValue());
          this.getValue().call(this.object);
        },
      });
      return d;
    })(dat.controllers.Controller, dat.dom.dom, dat.utils.common);
    dat.controllers.BooleanController = (function (e, a, c) {
      var d = function (c, b) {
        d.superclass.call(this, c, b);
        var e = this;
        this.__prev = this.getValue();
        this.__checkbox = document.createElement("input");
        this.__checkbox.setAttribute("type", "checkbox");
        a.bind(
          this.__checkbox,
          "change",
          function () {
            e.setValue(!e.__prev);
          },
          false
        );
        this.domElement.appendChild(this.__checkbox);
        this.updateDisplay();
      };
      d.superclass = e;
      c.extend(d.prototype, e.prototype, {
        setValue: function (a) {
          a = d.superclass.prototype.setValue.call(this, a);
          this.__onFinishChange &&
            this.__onFinishChange.call(this, this.getValue());
          this.__prev = this.getValue();
          return a;
        },
        updateDisplay: function () {
          this.getValue() === true
            ? (this.__checkbox.setAttribute("checked", "checked"),
              (this.__checkbox.checked = true))
            : (this.__checkbox.checked = false);
          return d.superclass.prototype.updateDisplay.call(this);
        },
      });
      return d;
    })(dat.controllers.Controller, dat.dom.dom, dat.utils.common);
    dat.color.toString = (function (e) {
      return function (a) {
        if (a.a == 1 || e.isUndefined(a.a)) {
          for (a = a.hex.toString(16); a.length < 6; ) a = "0" + a;
          return "#" + a;
        } else
          return (
            "rgba(" +
            Math.round(a.r) +
            "," +
            Math.round(a.g) +
            "," +
            Math.round(a.b) +
            "," +
            a.a +
            ")"
          );
      };
    })(dat.utils.common);
    dat.color.interpret = (function (e, a) {
      var c,
        d,
        f = [
          {
            litmus: a.isString,
            conversions: {
              THREE_CHAR_HEX: {
                read: function (a) {
                  a = a.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);
                  return a === null
                    ? false
                    : {
                        space: "HEX",
                        hex: parseInt(
                          "0x" +
                            a[1].toString() +
                            a[1].toString() +
                            a[2].toString() +
                            a[2].toString() +
                            a[3].toString() +
                            a[3].toString()
                        ),
                      };
                },
                write: e,
              },
              SIX_CHAR_HEX: {
                read: function (a) {
                  a = a.match(/^#([A-F0-9]{6})$/i);
                  return a === null
                    ? false
                    : {
                        space: "HEX",
                        hex: parseInt("0x" + a[1].toString()),
                      };
                },
                write: e,
              },
              CSS_RGB: {
                read: function (a) {
                  a = a.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);
                  return a === null
                    ? false
                    : {
                        space: "RGB",
                        r: parseFloat(a[1]),
                        g: parseFloat(a[2]),
                        b: parseFloat(a[3]),
                      };
                },
                write: e,
              },
              CSS_RGBA: {
                read: function (a) {
                  a = a.match(
                    /^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\,\s*(.+)\s*\)/
                  );
                  return a === null
                    ? false
                    : {
                        space: "RGB",
                        r: parseFloat(a[1]),
                        g: parseFloat(a[2]),
                        b: parseFloat(a[3]),
                        a: parseFloat(a[4]),
                      };
                },
                write: e,
              },
            },
          },
          {
            litmus: a.isNumber,
            conversions: {
              HEX: {
                read: function (a) {
                  return {
                    space: "HEX",
                    hex: a,
                    conversionName: "HEX",
                  };
                },
                write: function (a) {
                  return a.hex;
                },
              },
            },
          },
          {
            litmus: a.isArray,
            conversions: {
              RGB_ARRAY: {
                read: function (a) {
                  return a.length != 3
                    ? false
                    : {
                        space: "RGB",
                        r: a[0],
                        g: a[1],
                        b: a[2],
                      };
                },
                write: function (a) {
                  return [a.r, a.g, a.b];
                },
              },
              RGBA_ARRAY: {
                read: function (a) {
                  return a.length != 4
                    ? false
                    : {
                        space: "RGB",
                        r: a[0],
                        g: a[1],
                        b: a[2],
                        a: a[3],
                      };
                },
                write: function (a) {
                  return [a.r, a.g, a.b, a.a];
                },
              },
            },
          },
          {
            litmus: a.isObject,
            conversions: {
              RGBA_OBJ: {
                read: function (b) {
                  return a.isNumber(b.r) &&
                    a.isNumber(b.g) &&
                    a.isNumber(b.b) &&
                    a.isNumber(b.a)
                    ? {
                        space: "RGB",
                        r: b.r,
                        g: b.g,
                        b: b.b,
                        a: b.a,
                      }
                    : false;
                },
                write: function (a) {
                  return {
                    r: a.r,
                    g: a.g,
                    b: a.b,
                    a: a.a,
                  };
                },
              },
              RGB_OBJ: {
                read: function (b) {
                  return a.isNumber(b.r) && a.isNumber(b.g) && a.isNumber(b.b)
                    ? {
                        space: "RGB",
                        r: b.r,
                        g: b.g,
                        b: b.b,
                      }
                    : false;
                },
                write: function (a) {
                  return {
                    r: a.r,
                    g: a.g,
                    b: a.b,
                  };
                },
              },
              HSVA_OBJ: {
                read: function (b) {
                  return a.isNumber(b.h) &&
                    a.isNumber(b.s) &&
                    a.isNumber(b.v) &&
                    a.isNumber(b.a)
                    ? {
                        space: "HSV",
                        h: b.h,
                        s: b.s,
                        v: b.v,
                        a: b.a,
                      }
                    : false;
                },
                write: function (a) {
                  return {
                    h: a.h,
                    s: a.s,
                    v: a.v,
                    a: a.a,
                  };
                },
              },
              HSV_OBJ: {
                read: function (b) {
                  return a.isNumber(b.h) && a.isNumber(b.s) && a.isNumber(b.v)
                    ? {
                        space: "HSV",
                        h: b.h,
                        s: b.s,
                        v: b.v,
                      }
                    : false;
                },
                write: function (a) {
                  return {
                    h: a.h,
                    s: a.s,
                    v: a.v,
                  };
                },
              },
            },
          },
        ];
      return function () {
        d = false;
        var b = arguments.length > 1 ? a.toArray(arguments) : arguments[0];
        a.each(f, function (e) {
          if (e.litmus(b))
            return (
              a.each(e.conversions, function (e, f) {
                c = e.read(b);
                if (d === false && c !== false)
                  return (
                    (d = c), (c.conversionName = f), (c.conversion = e), a.BREAK
                  );
              }),
              a.BREAK
            );
        });
        return d;
      };
    })(dat.color.toString, dat.utils.common);
    dat.GUI = dat.gui.GUI = (function (
      e,
      a,
      c,
      d,
      f,
      b,
      n,
      h,
      j,
      m,
      l,
      o,
      y,
      g,
      i
    ) {
      function q(a, b, r, c) {
        if (b[r] === void 0)
          throw Error("Object " + b + ' has no property "' + r + '"');
        c.color
          ? (b = new l(b, r))
          : ((b = [b, r].concat(c.factoryArgs)), (b = d.apply(a, b)));
        if (c.before instanceof f) c.before = c.before.__li;
        t(a, b);
        g.addClass(b.domElement, "c");
        r = document.createElement("span");
        g.addClass(r, "property-name");
        r.innerHTML = b.property;
        var e = document.createElement("div");
        e.appendChild(r);
        e.appendChild(b.domElement);
        c = s(a, e, c.before);
        g.addClass(c, k.CLASS_CONTROLLER_ROW);
        g.addClass(c, typeof b.getValue());
        p(a, c, b);
        a.__controllers.push(b);
        return b;
      }
      function s(a, b, d) {
        var c = document.createElement("li");
        b && c.appendChild(b);
        d ? a.__ul.insertBefore(c, params.before) : a.__ul.appendChild(c);
        a.onResize();
        return c;
      }
      function p(a, d, c) {
        c.__li = d;
        c.__gui = a;
        i.extend(c, {
          options: function (b) {
            if (arguments.length > 1)
              return (
                c.remove(),
                q(a, c.object, c.property, {
                  before: c.__li.nextElementSibling,
                  factoryArgs: [i.toArray(arguments)],
                })
              );
            if (i.isArray(b) || i.isObject(b))
              return (
                c.remove(),
                q(a, c.object, c.property, {
                  before: c.__li.nextElementSibling,
                  factoryArgs: [b],
                })
              );
          },
          name: function (a) {
            c.__li.firstElementChild.firstElementChild.innerHTML = a;
            return c;
          },
          listen: function () {
            c.__gui.listen(c);
            return c;
          },
          remove: function () {
            c.__gui.remove(c);
            return c;
          },
        });
        if (c instanceof j) {
          var e = new h(c.object, c.property, {
            min: c.__min,
            max: c.__max,
            step: c.__step,
          });
          i.each(["updateDisplay", "onChange", "onFinishChange"], function (a) {
            var b = c[a],
              H = e[a];
            c[a] = e[a] = function () {
              var a = Array.prototype.slice.call(arguments);
              b.apply(c, a);
              return H.apply(e, a);
            };
          });
          g.addClass(d, "has-slider");
          c.domElement.insertBefore(
            e.domElement,
            c.domElement.firstElementChild
          );
        } else if (c instanceof h) {
          var f = function (b) {
            return i.isNumber(c.__min) && i.isNumber(c.__max)
              ? (c.remove(),
                q(a, c.object, c.property, {
                  before: c.__li.nextElementSibling,
                  factoryArgs: [c.__min, c.__max, c.__step],
                }))
              : b;
          };
          c.min = i.compose(f, c.min);
          c.max = i.compose(f, c.max);
        } else if (c instanceof b)
          g.bind(d, "click", function () {
            g.fakeEvent(c.__checkbox, "click");
          }),
            g.bind(c.__checkbox, "click", function (a) {
              a.stopPropagation();
            });
        else if (c instanceof n)
          g.bind(d, "click", function () {
            g.fakeEvent(c.__button, "click");
          }),
            g.bind(d, "mouseover", function () {
              g.addClass(c.__button, "hover");
            }),
            g.bind(d, "mouseout", function () {
              g.removeClass(c.__button, "hover");
            });
        else if (c instanceof l)
          g.addClass(d, "color"),
            (c.updateDisplay = i.compose(function (a) {
              d.style.borderLeftColor = c.__color.toString();
              return a;
            }, c.updateDisplay)),
            c.updateDisplay();
        c.setValue = i.compose(function (b) {
          a.getRoot().__preset_select && c.isModified() && B(a.getRoot(), true);
          return b;
        }, c.setValue);
      }
      function t(a, b) {
        var c = a.getRoot(),
          d = c.__rememberedObjects.indexOf(b.object);
        if (d != -1) {
          var e = c.__rememberedObjectIndecesToControllers[d];
          e === void 0 &&
            ((e = {}), (c.__rememberedObjectIndecesToControllers[d] = e));
          e[b.property] = b;
          if (c.load && c.load.remembered) {
            c = c.load.remembered;
            if (c[a.preset]) c = c[a.preset];
            else if (c[w]) c = c[w];
            else return;
            if (c[d] && c[d][b.property] !== void 0)
              (d = c[d][b.property]), (b.initialValue = d), b.setValue(d);
          }
        }
      }
      function I(a) {
        var b = (a.__save_row = document.createElement("li"));
        g.addClass(a.domElement, "has-save");
        a.__ul.insertBefore(b, a.__ul.firstChild);
        g.addClass(b, "save-row");
        var c = document.createElement("span");
        c.innerHTML = "&nbsp;";
        g.addClass(c, "button gears");
        var d = document.createElement("span");
        d.innerHTML = "Save";
        g.addClass(d, "button");
        g.addClass(d, "save");
        var e = document.createElement("span");
        e.innerHTML = "New";
        g.addClass(e, "button");
        g.addClass(e, "save-as");
        var f = document.createElement("span");
        f.innerHTML = "Revert";
        g.addClass(f, "button");
        g.addClass(f, "revert");
        var m = (a.__preset_select = document.createElement("select"));
        a.load && a.load.remembered
          ? i.each(a.load.remembered, function (b, c) {
              C(a, c, c == a.preset);
            })
          : C(a, w, false);
        g.bind(m, "change", function () {
          for (var b = 0; b < a.__preset_select.length; b++)
            a.__preset_select[b].innerHTML = a.__preset_select[b].value;
          a.preset = this.value;
        });
        b.appendChild(m);
        b.appendChild(c);
        b.appendChild(d);
        b.appendChild(e);
        b.appendChild(f);
        if (u) {
          var b = document.getElementById("dg-save-locally"),
            l = document.getElementById("dg-local-explain");
          b.style.display = "block";
          b = document.getElementById("dg-local-storage");
          localStorage.getItem(document.location.href + ".isLocal") ===
            "true" && b.setAttribute("checked", "checked");
          var o = function () {
            l.style.display = a.useLocalStorage ? "block" : "none";
          };
          o();
          g.bind(b, "change", function () {
            a.useLocalStorage = !a.useLocalStorage;
            o();
          });
        }
        var h = document.getElementById("dg-new-constructor");
        g.bind(h, "keydown", function (a) {
          a.metaKey && (a.which === 67 || a.keyCode == 67) && x.hide();
        });
        g.bind(c, "click", function () {
          h.innerHTML = JSON.stringify(a.getSaveObject(), void 0, 2);
          x.show();
          h.focus();
          h.select();
        });
        g.bind(d, "click", function () {
          a.save();
        });
        g.bind(e, "click", function () {
          var b = prompt("Enter a new preset name.");
          b && a.saveAs(b);
        });
        g.bind(f, "click", function () {
          a.revert();
        });
      }
      function J(a) {
        function b(f) {
          f.preventDefault();
          e = f.clientX;
          g.addClass(a.__closeButton, k.CLASS_DRAG);
          g.bind(window, "mousemove", c);
          g.bind(window, "mouseup", d);
          return false;
        }
        function c(b) {
          b.preventDefault();
          a.width += e - b.clientX;
          a.onResize();
          e = b.clientX;
          return false;
        }
        function d() {
          g.removeClass(a.__closeButton, k.CLASS_DRAG);
          g.unbind(window, "mousemove", c);
          g.unbind(window, "mouseup", d);
        }
        a.__resize_handle = document.createElement("div");
        i.extend(a.__resize_handle.style, {
          width: "6px",
          marginLeft: "-3px",
          height: "200px",
          cursor: "ew-resize",
          position: "absolute",
        });
        var e;
        g.bind(a.__resize_handle, "mousedown", b);
        g.bind(a.__closeButton, "mousedown", b);
        a.domElement.insertBefore(
          a.__resize_handle,
          a.domElement.firstElementChild
        );
      }
      function D(a, b) {
        a.domElement.style.width = b + "px";
        if (a.__save_row && a.autoPlace) a.__save_row.style.width = b + "px";
        if (a.__closeButton) a.__closeButton.style.width = b + "px";
      }
      function z(a, b) {
        var c = {};
        i.each(a.__rememberedObjects, function (d, e) {
          var f = {};
          i.each(a.__rememberedObjectIndecesToControllers[e], function (a, c) {
            f[c] = b ? a.initialValue : a.getValue();
          });
          c[e] = f;
        });
        return c;
      }
      function C(a, b, c) {
        var d = document.createElement("option");
        d.innerHTML = b;
        d.value = b;
        a.__preset_select.appendChild(d);
        if (c) a.__preset_select.selectedIndex = a.__preset_select.length - 1;
      }
      function B(a, b) {
        var c = a.__preset_select[a.__preset_select.selectedIndex];
        c.innerHTML = b ? c.value + "*" : c.value;
      }
      function E(a) {
        a.length != 0 &&
          o(function () {
            E(a);
          });
        i.each(a, function (a) {
          a.updateDisplay();
        });
      }
      e.inject(c);
      var w = "Default",
        u;
      try {
        u = "localStorage" in window && window.localStorage !== null;
      } catch (K) {
        u = false;
      }
      var x,
        F = true,
        v,
        A = false,
        G = [],
        k = function (a) {
          function b() {
            localStorage.setItem(
              document.location.href + ".gui",
              JSON.stringify(d.getSaveObject())
            );
          }
          function c() {
            var a = d.getRoot();
            a.width += 1;
            i.defer(function () {
              a.width -= 1;
            });
          }
          var d = this;
          this.domElement = document.createElement("div");
          this.__ul = document.createElement("ul");
          this.domElement.appendChild(this.__ul);
          g.addClass(this.domElement, "dg");
          this.__folders = {};
          this.__controllers = [];
          this.__rememberedObjects = [];
          this.__rememberedObjectIndecesToControllers = [];
          this.__listening = [];
          a = a || {};
          a = i.defaults(a, {
            autoPlace: true,
            width: k.DEFAULT_WIDTH,
          });
          a = i.defaults(a, {
            resizable: a.autoPlace,
            hideable: a.autoPlace,
          });
          if (i.isUndefined(a.load))
            a.load = {
              preset: w,
            };
          else if (a.preset) a.load.preset = a.preset;
          i.isUndefined(a.parent) && a.hideable && G.push(this);
          a.resizable = i.isUndefined(a.parent) && a.resizable;
          if (a.autoPlace && i.isUndefined(a.scrollable)) a.scrollable = true;
          var e =
            u &&
            localStorage.getItem(document.location.href + ".isLocal") ===
              "true";
          Object.defineProperties(this, {
            parent: {
              get: function () {
                return a.parent;
              },
            },
            scrollable: {
              get: function () {
                return a.scrollable;
              },
            },
            autoPlace: {
              get: function () {
                return a.autoPlace;
              },
            },
            preset: {
              get: function () {
                return d.parent ? d.getRoot().preset : a.load.preset;
              },
              set: function (b) {
                d.parent ? (d.getRoot().preset = b) : (a.load.preset = b);
                for (b = 0; b < this.__preset_select.length; b++)
                  if (this.__preset_select[b].value == this.preset)
                    this.__preset_select.selectedIndex = b;
                d.revert();
              },
            },
            width: {
              get: function () {
                return a.width;
              },
              set: function (b) {
                a.width = b;
                D(d, b);
              },
            },
            name: {
              get: function () {
                return a.name;
              },
              set: function (b) {
                a.name = b;
                if (m) m.innerHTML = a.name;
              },
            },
            closed: {
              get: function () {
                return a.closed;
              },
              set: function (b) {
                a.closed = b;
                a.closed
                  ? g.addClass(d.__ul, k.CLASS_CLOSED)
                  : g.removeClass(d.__ul, k.CLASS_CLOSED);
                this.onResize();
                if (d.__closeButton)
                  d.__closeButton.innerHTML = b ? k.TEXT_OPEN : k.TEXT_CLOSED;
              },
            },
            load: {
              get: function () {
                return a.load;
              },
            },
            useLocalStorage: {
              get: function () {
                return e;
              },
              set: function (a) {
                u &&
                  ((e = a)
                    ? g.bind(window, "unload", b)
                    : g.unbind(window, "unload", b),
                  localStorage.setItem(document.location.href + ".isLocal", a));
              },
            },
          });
          if (i.isUndefined(a.parent)) {
            a.closed = false;
            g.addClass(this.domElement, k.CLASS_MAIN);
            g.makeSelectable(this.domElement, false);
            if (u && e) {
              d.useLocalStorage = true;
              var f = localStorage.getItem(document.location.href + ".gui");
              if (f) a.load = JSON.parse(f);
            }
            this.__closeButton = document.createElement("div");
            this.__closeButton.innerHTML = k.TEXT_CLOSED;
            g.addClass(this.__closeButton, k.CLASS_CLOSE_BUTTON);
            this.domElement.appendChild(this.__closeButton);
            g.bind(this.__closeButton, "click", function () {
              d.closed = !d.closed;
            });
          } else {
            if (a.closed === void 0) a.closed = true;
            var m = document.createTextNode(a.name);
            g.addClass(m, "controller-name");
            f = s(d, m);
            g.addClass(this.__ul, k.CLASS_CLOSED);
            g.addClass(f, "title");
            g.bind(f, "click", function (a) {
              a.preventDefault();
              d.closed = !d.closed;
              return false;
            });
            if (!a.closed) this.closed = false;
          }
          a.autoPlace &&
            (i.isUndefined(a.parent) &&
              (F &&
                ((v = document.createElement("div")),
                g.addClass(v, "dg"),
                g.addClass(v, k.CLASS_AUTO_PLACE_CONTAINER),
                document.body.appendChild(v),
                (F = false)),
              v.appendChild(this.domElement),
              g.addClass(this.domElement, k.CLASS_AUTO_PLACE)),
            this.parent || D(d, a.width));
          g.bind(window, "resize", function () {
            d.onResize();
          });
          g.bind(this.__ul, "webkitTransitionEnd", function () {
            d.onResize();
          });
          g.bind(this.__ul, "transitionend", function () {
            d.onResize();
          });
          g.bind(this.__ul, "oTransitionEnd", function () {
            d.onResize();
          });
          this.onResize();
          a.resizable && J(this);
          d.getRoot();
          a.parent || c();
        };
      k.toggleHide = function () {
        A = !A;
        i.each(G, function (a) {
          a.domElement.style.zIndex = A ? -999 : 999;
          a.domElement.style.opacity = A ? 0 : 1;
        });
      };
      k.CLASS_AUTO_PLACE = "a";
      k.CLASS_AUTO_PLACE_CONTAINER = "ac";
      k.CLASS_MAIN = "main";
      k.CLASS_CONTROLLER_ROW = "cr";
      k.CLASS_TOO_TALL = "taller-than-window";
      k.CLASS_CLOSED = "closed";
      k.CLASS_CLOSE_BUTTON = "close-button";
      k.CLASS_DRAG = "drag";
      k.DEFAULT_WIDTH = 245;
      k.TEXT_CLOSED = "Close Controls";
      k.TEXT_OPEN = "Open Controls";
      g.bind(
        window,
        "keydown",
        function (a) {
          document.activeElement.type !== "text" &&
            (a.which === 72 || a.keyCode == 72) &&
            k.toggleHide();
        },
        false
      );
      i.extend(k.prototype, {
        add: function (a, b) {
          return q(this, a, b, {
            factoryArgs: Array.prototype.slice.call(arguments, 2),
          });
        },
        addColor: function (a, b) {
          return q(this, a, b, {
            color: true,
          });
        },
        remove: function (a) {
          this.__ul.removeChild(a.__li);
          this.__controllers.slice(this.__controllers.indexOf(a), 1);
          var b = this;
          i.defer(function () {
            b.onResize();
          });
        },
        destroy: function () {
          this.autoPlace && v.removeChild(this.domElement);
        },
        addFolder: function (a) {
          if (this.__folders[a] !== void 0)
            throw Error(
              'You already have a folder in this GUI by the name "' + a + '"'
            );
          var b = {
            name: a,
            parent: this,
          };
          b.autoPlace = this.autoPlace;
          if (this.load && this.load.folders && this.load.folders[a])
            (b.closed = this.load.folders[a].closed),
              (b.load = this.load.folders[a]);
          b = new k(b);
          this.__folders[a] = b;
          a = s(this, b.domElement);
          g.addClass(a, "folder");
          return b;
        },
        open: function () {
          this.closed = false;
        },
        close: function () {
          this.closed = true;
        },
        onResize: function () {
          var a = this.getRoot();
          if (a.scrollable) {
            var b = g.getOffset(a.__ul).top,
              c = 0;
            i.each(a.__ul.childNodes, function (b) {
              (a.autoPlace && b === a.__save_row) || (c += g.getHeight(b));
            });
            window.innerHeight - b - 20 < c
              ? (g.addClass(a.domElement, k.CLASS_TOO_TALL),
                (a.__ul.style.height = window.innerHeight - b - 20 + "px"))
              : (g.removeClass(a.domElement, k.CLASS_TOO_TALL),
                (a.__ul.style.height = "auto"));
          }
          a.__resize_handle &&
            i.defer(function () {
              a.__resize_handle.style.height = a.__ul.offsetHeight + "px";
            });
          if (a.__closeButton) a.__closeButton.style.width = a.width + "px";
        },
        remember: function () {
          if (i.isUndefined(x)) (x = new y()), (x.domElement.innerHTML = a);
          if (this.parent)
            throw Error("You can only call remember on a top level GUI.");
          var b = this;
          i.each(Array.prototype.slice.call(arguments), function (a) {
            b.__rememberedObjects.length == 0 && I(b);
            b.__rememberedObjects.indexOf(a) == -1 &&
              b.__rememberedObjects.push(a);
          });
          this.autoPlace && D(this, this.width);
        },
        getRoot: function () {
          for (var a = this; a.parent; ) a = a.parent;
          return a;
        },
        getSaveObject: function () {
          var a = this.load;
          a.closed = this.closed;
          if (this.__rememberedObjects.length > 0) {
            a.preset = this.preset;
            if (!a.remembered) a.remembered = {};
            a.remembered[this.preset] = z(this);
          }
          a.folders = {};
          i.each(this.__folders, function (b, c) {
            a.folders[c] = b.getSaveObject();
          });
          return a;
        },
        save: function () {
          if (!this.load.remembered) this.load.remembered = {};
          this.load.remembered[this.preset] = z(this);
          B(this, false);
        },
        saveAs: function (a) {
          if (!this.load.remembered)
            (this.load.remembered = {}),
              (this.load.remembered[w] = z(this, true));
          this.load.remembered[a] = z(this);
          this.preset = a;
          C(this, a, true);
        },
        revert: function (a) {
          i.each(
            this.__controllers,
            function (b) {
              this.getRoot().load.remembered
                ? t(a || this.getRoot(), b)
                : b.setValue(b.initialValue);
            },
            this
          );
          i.each(this.__folders, function (a) {
            a.revert(a);
          });
          a || B(this.getRoot(), false);
        },
        listen: function (a) {
          var b = this.__listening.length == 0;
          this.__listening.push(a);
          b && E(this.__listening);
        },
      });
      return k;
    })(
      dat.utils.css,
      '<div id="dg-save" class="dg dialogue">\n\n  Here\'s the new load parameter for your <code>GUI</code>\'s constructor:\n\n  <textarea id="dg-new-constructor"></textarea>\n\n  <div id="dg-save-locally">\n\n    <input id="dg-local-storage" type="checkbox"/> Automatically save\n    values to <code>localStorage</code> on exit.\n\n    <div id="dg-local-explain">The values saved to <code>localStorage</code> will\n      override those passed to <code>dat.GUI</code>\'s constructor. This makes it\n      easier to work incrementally, but <code>localStorage</code> is fragile,\n      and your friends may not see the same values you do.\n      \n    </div>\n    \n  </div>\n\n</div>',
      ".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1 !important}.dg.main:hover .close-button,.dg.main .close-button.drag{opacity:1}.dg.main .close-button{-webkit-transition:opacity 0.1s linear;-o-transition:opacity 0.1s linear;-moz-transition:opacity 0.1s linear;transition:opacity 0.1s linear;border:0;position:absolute;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-x:hidden}.dg.a.has-save ul{margin-top:27px}.dg.a.has-save ul.closed{margin-top:0}.dg.a .save-row{position:fixed;top:0;z-index:1002}.dg li{-webkit-transition:height 0.1s ease-out;-o-transition:height 0.1s ease-out;-moz-transition:height 0.1s ease-out;transition:height 0.1s ease-out}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;overflow:hidden;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid rgba(0,0,0,0)}.dg li.title{cursor:pointer;margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li > *{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:9px}.dg .c select{margin-top:5px}.dg .cr.function,.dg .cr.function .property-name,.dg .cr.function *,.dg .cr.boolean,.dg .cr.boolean *{cursor:pointer}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0px 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco, monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px 'Lucida Grande', sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px 4px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url() 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url() 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid rgba(255,255,255,0.2)}.dg .closed li.title{background-image:url()}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.function:hover,.dg .cr.boolean:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}\n",
      (dat.controllers.factory = (function (e, a, c, d, f, b, n) {
        return function (h, j, m, l) {
          var o = h[j];
          if (n.isArray(m) || n.isObject(m)) return new e(h, j, m);
          if (n.isNumber(o))
            return n.isNumber(m) && n.isNumber(l)
              ? new c(h, j, m, l)
              : new a(h, j, {
                  min: m,
                  max: l,
                });
          if (n.isString(o)) return new d(h, j);
          if (n.isFunction(o)) return new f(h, j, "");
          if (n.isBoolean(o)) return new b(h, j);
        };
      })(
        dat.controllers.OptionController,
        dat.controllers.NumberControllerBox,
        dat.controllers.NumberControllerSlider,
        (dat.controllers.StringController = (function (e, a, c) {
          var d = function (c, b) {
            function e() {
              h.setValue(h.__input.value);
            }
            d.superclass.call(this, c, b);
            var h = this;
            this.__input = document.createElement("input");
            this.__input.setAttribute("type", "text");
            a.bind(this.__input, "keyup", e);
            a.bind(this.__input, "change", e);
            a.bind(this.__input, "blur", function () {
              h.__onFinishChange && h.__onFinishChange.call(h, h.getValue());
            });
            a.bind(this.__input, "keydown", function (a) {
              a.keyCode === 13 && this.blur();
            });
            this.updateDisplay();
            this.domElement.appendChild(this.__input);
          };
          d.superclass = e;
          c.extend(d.prototype, e.prototype, {
            updateDisplay: function () {
              if (!a.isActive(this.__input))
                this.__input.value = this.getValue();
              return d.superclass.prototype.updateDisplay.call(this);
            },
          });
          return d;
        })(dat.controllers.Controller, dat.dom.dom, dat.utils.common)),
        dat.controllers.FunctionController,
        dat.controllers.BooleanController,
        dat.utils.common
      )),
      dat.controllers.Controller,
      dat.controllers.BooleanController,
      dat.controllers.FunctionController,
      dat.controllers.NumberControllerBox,
      dat.controllers.NumberControllerSlider,
      dat.controllers.OptionController,
      (dat.controllers.ColorController = (function (e, a, c, d, f) {
        function b(a, b, c, d) {
          a.style.background = "";
          f.each(j, function (e) {
            a.style.cssText +=
              "background: " +
              e +
              "linear-gradient(" +
              b +
              ", " +
              c +
              " 0%, " +
              d +
              " 100%); ";
          });
        }
        function n(a) {
          a.style.background = "";
          a.style.cssText +=
            "background: -moz-linear-gradient(top,  #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);";
          a.style.cssText +=
            "background: -webkit-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
          a.style.cssText +=
            "background: -o-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
          a.style.cssText +=
            "background: -ms-linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
          a.style.cssText +=
            "background: linear-gradient(top,  #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);";
        }
        var h = function (e, l) {
          function o(b) {
            q(b);
            a.bind(window, "mousemove", q);
            a.bind(window, "mouseup", j);
          }
          function j() {
            a.unbind(window, "mousemove", q);
            a.unbind(window, "mouseup", j);
          }
          function g() {
            var a = d(this.value);
            a !== false
              ? ((p.__color.__state = a), p.setValue(p.__color.toOriginal()))
              : (this.value = p.__color.toString());
          }
          function i() {
            a.unbind(window, "mousemove", s);
            a.unbind(window, "mouseup", i);
          }
          function q(b) {
            b.preventDefault();
            var c = a.getWidth(p.__saturation_field),
              d = a.getOffset(p.__saturation_field),
              e = (b.clientX - d.left + document.body.scrollLeft) / c,
              b = 1 - (b.clientY - d.top + document.body.scrollTop) / c;
            b > 1 ? (b = 1) : b < 0 && (b = 0);
            e > 1 ? (e = 1) : e < 0 && (e = 0);
            p.__color.v = b;
            p.__color.s = e;
            p.setValue(p.__color.toOriginal());
            return false;
          }
          function s(b) {
            b.preventDefault();
            var c = a.getHeight(p.__hue_field),
              d = a.getOffset(p.__hue_field),
              b = 1 - (b.clientY - d.top + document.body.scrollTop) / c;
            b > 1 ? (b = 1) : b < 0 && (b = 0);
            p.__color.h = b * 360;
            p.setValue(p.__color.toOriginal());
            return false;
          }
          h.superclass.call(this, e, l);
          this.__color = new c(this.getValue());
          this.__temp = new c(0);
          var p = this;
          this.domElement = document.createElement("div");
          a.makeSelectable(this.domElement, false);
          this.__selector = document.createElement("div");
          this.__selector.className = "selector";
          this.__saturation_field = document.createElement("div");
          this.__saturation_field.className = "saturation-field";
          this.__field_knob = document.createElement("div");
          this.__field_knob.className = "field-knob";
          this.__field_knob_border = "2px solid ";
          this.__hue_knob = document.createElement("div");
          this.__hue_knob.className = "hue-knob";
          this.__hue_field = document.createElement("div");
          this.__hue_field.className = "hue-field";
          this.__input = document.createElement("input");
          this.__input.type = "text";
          this.__input_textShadow = "0 1px 1px ";
          a.bind(this.__input, "keydown", function (a) {
            a.keyCode === 13 && g.call(this);
          });
          a.bind(this.__input, "blur", g);
          a.bind(this.__selector, "mousedown", function () {
            a.addClass(this, "drag").bind(window, "mouseup", function () {
              a.removeClass(p.__selector, "drag");
            });
          });
          var t = document.createElement("div");
          f.extend(this.__selector.style, {
            width: "122px",
            height: "102px",
            padding: "3px",
            backgroundColor: "#222",
            boxShadow: "0px 1px 3px rgba(0,0,0,0.3)",
          });
          f.extend(this.__field_knob.style, {
            position: "absolute",
            width: "12px",
            height: "12px",
            border:
              this.__field_knob_border +
              (this.__color.v < 0.5 ? "#fff" : "#000"),
            boxShadow: "0px 1px 3px rgba(0,0,0,0.5)",
            borderRadius: "12px",
            zIndex: 1,
          });
          f.extend(this.__hue_knob.style, {
            position: "absolute",
            width: "15px",
            height: "2px",
            borderRight: "4px solid #fff",
            zIndex: 1,
          });
          f.extend(this.__saturation_field.style, {
            width: "100px",
            height: "100px",
            border: "1px solid #555",
            marginRight: "3px",
            display: "inline-block",
            cursor: "pointer",
          });
          f.extend(t.style, {
            width: "100%",
            height: "100%",
            background: "none",
          });
          b(t, "top", "rgba(0,0,0,0)", "#000");
          f.extend(this.__hue_field.style, {
            width: "15px",
            height: "100px",
            display: "inline-block",
            border: "1px solid #555",
            cursor: "ns-resize",
          });
          n(this.__hue_field);
          f.extend(this.__input.style, {
            outline: "none",
            textAlign: "center",
            color: "#fff",
            border: 0,
            fontWeight: "bold",
            textShadow: this.__input_textShadow + "rgba(0,0,0,0.7)",
          });
          a.bind(this.__saturation_field, "mousedown", o);
          a.bind(this.__field_knob, "mousedown", o);
          a.bind(this.__hue_field, "mousedown", function (b) {
            s(b);
            a.bind(window, "mousemove", s);
            a.bind(window, "mouseup", i);
          });
          this.__saturation_field.appendChild(t);
          this.__selector.appendChild(this.__field_knob);
          this.__selector.appendChild(this.__saturation_field);
          this.__selector.appendChild(this.__hue_field);
          this.__hue_field.appendChild(this.__hue_knob);
          this.domElement.appendChild(this.__input);
          this.domElement.appendChild(this.__selector);
          this.updateDisplay();
        };
        h.superclass = e;
        f.extend(h.prototype, e.prototype, {
          updateDisplay: function () {
            var a = d(this.getValue());
            if (a !== false) {
              var e = false;
              f.each(
                c.COMPONENTS,
                function (b) {
                  if (
                    !f.isUndefined(a[b]) &&
                    !f.isUndefined(this.__color.__state[b]) &&
                    a[b] !== this.__color.__state[b]
                  )
                    return (e = true), {};
                },
                this
              );
              e && f.extend(this.__color.__state, a);
            }
            f.extend(this.__temp.__state, this.__color.__state);
            this.__temp.a = 1;
            var h = this.__color.v < 0.5 || this.__color.s > 0.5 ? 255 : 0,
              j = 255 - h;
            f.extend(this.__field_knob.style, {
              marginLeft: 100 * this.__color.s - 7 + "px",
              marginTop: 100 * (1 - this.__color.v) - 7 + "px",
              backgroundColor: this.__temp.toString(),
              border:
                this.__field_knob_border + "rgb(" + h + "," + h + "," + h + ")",
            });
            this.__hue_knob.style.marginTop =
              (1 - this.__color.h / 360) * 100 + "px";
            this.__temp.s = 1;
            this.__temp.v = 1;
            b(this.__saturation_field, "left", "#fff", this.__temp.toString());
            f.extend(this.__input.style, {
              backgroundColor: (this.__input.value = this.__color.toString()),
              color: "rgb(" + h + "," + h + "," + h + ")",
              textShadow:
                this.__input_textShadow +
                "rgba(" +
                j +
                "," +
                j +
                "," +
                j +
                ",.7)",
            });
          },
        });
        var j = ["-moz-", "-o-", "-webkit-", "-ms-", ""];
        return h;
      })(
        dat.controllers.Controller,
        dat.dom.dom,
        (dat.color.Color = (function (e, a, c, d) {
          function f(a, b, c) {
            Object.defineProperty(a, b, {
              get: function () {
                if (this.__state.space === "RGB") return this.__state[b];
                n(this, b, c);
                return this.__state[b];
              },
              set: function (a) {
                if (this.__state.space !== "RGB")
                  n(this, b, c), (this.__state.space = "RGB");
                this.__state[b] = a;
              },
            });
          }
          function b(a, b) {
            Object.defineProperty(a, b, {
              get: function () {
                if (this.__state.space === "HSV") return this.__state[b];
                h(this);
                return this.__state[b];
              },
              set: function (a) {
                if (this.__state.space !== "HSV")
                  h(this), (this.__state.space = "HSV");
                this.__state[b] = a;
              },
            });
          }
          function n(b, c, e) {
            if (b.__state.space === "HEX")
              b.__state[c] = a.component_from_hex(b.__state.hex, e);
            else if (b.__state.space === "HSV")
              d.extend(
                b.__state,
                a.hsv_to_rgb(b.__state.h, b.__state.s, b.__state.v)
              );
            else throw "Corrupted color state";
          }
          function h(b) {
            var c = a.rgb_to_hsv(b.r, b.g, b.b);
            d.extend(b.__state, {
              s: c.s,
              v: c.v,
            });
            if (d.isNaN(c.h)) {
              if (d.isUndefined(b.__state.h)) b.__state.h = 0;
            } else b.__state.h = c.h;
          }
          var j = function () {
            this.__state = e.apply(this, arguments);
            if (this.__state === false)
              throw "Failed to interpret color arguments";
            this.__state.a = this.__state.a || 1;
          };
          j.COMPONENTS = "r,g,b,h,s,v,hex,a".split(",");
          d.extend(j.prototype, {
            toString: function () {
              return c(this);
            },
            toOriginal: function () {
              return this.__state.conversion.write(this);
            },
          });
          f(j.prototype, "r", 2);
          f(j.prototype, "g", 1);
          f(j.prototype, "b", 0);
          b(j.prototype, "h");
          b(j.prototype, "s");
          b(j.prototype, "v");
          Object.defineProperty(j.prototype, "a", {
            get: function () {
              return this.__state.a;
            },
            set: function (a) {
              this.__state.a = a;
            },
          });
          Object.defineProperty(j.prototype, "hex", {
            get: function () {
              if (!this.__state.space !== "HEX")
                this.__state.hex = a.rgb_to_hex(this.r, this.g, this.b);
              return this.__state.hex;
            },
            set: function (a) {
              this.__state.space = "HEX";
              this.__state.hex = a;
            },
          });
          return j;
        })(
          dat.color.interpret,
          (dat.color.math = (function () {
            var e;
            return {
              hsv_to_rgb: function (a, c, d) {
                var e = a / 60 - Math.floor(a / 60),
                  b = d * (1 - c),
                  n = d * (1 - e * c),
                  c = d * (1 - (1 - e) * c),
                  a = [
                    [d, c, b],
                    [n, d, b],
                    [b, d, c],
                    [b, n, d],
                    [c, b, d],
                    [d, b, n],
                  ][Math.floor(a / 60) % 6];
                return {
                  r: a[0] * 255,
                  g: a[1] * 255,
                  b: a[2] * 255,
                };
              },
              rgb_to_hsv: function (a, c, d) {
                var e = Math.min(a, c, d),
                  b = Math.max(a, c, d),
                  e = b - e;
                if (b == 0)
                  return {
                    h: NaN,
                    s: 0,
                    v: 0,
                  };
                a =
                  a == b
                    ? (c - d) / e
                    : c == b
                    ? 2 + (d - a) / e
                    : 4 + (a - c) / e;
                a /= 6;
                a < 0 && (a += 1);
                return {
                  h: a * 360,
                  s: e / b,
                  v: b / 255,
                };
              },
              rgb_to_hex: function (a, c, d) {
                a = this.hex_with_component(0, 2, a);
                a = this.hex_with_component(a, 1, c);
                return (a = this.hex_with_component(a, 0, d));
              },
              component_from_hex: function (a, c) {
                return (a >> (c * 8)) & 255;
              },
              hex_with_component: function (a, c, d) {
                return (d << (e = c * 8)) | (a & ~(255 << e));
              },
            };
          })()),
          dat.color.toString,
          dat.utils.common
        )),
        dat.color.interpret,
        dat.utils.common
      )),
      (dat.utils.requestAnimationFrame = (function () {
        return (
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function (e) {
            window.setTimeout(e, 1e3 / 60);
          }
        );
      })()),
      (dat.dom.CenteredDiv = (function (e, a) {
        var c = function () {
          this.backgroundElement = document.createElement("div");
          a.extend(this.backgroundElement.style, {
            backgroundColor: "rgba(0,0,0,0.8)",
            top: 0,
            left: 0,
            display: "none",
            zIndex: "1000",
            opacity: 0,
            WebkitTransition: "opacity 0.2s linear",
          });
          e.makeFullscreen(this.backgroundElement);
          this.backgroundElement.style.position = "fixed";
          this.domElement = document.createElement("div");
          a.extend(this.domElement.style, {
            position: "fixed",
            display: "none",
            zIndex: "1001",
            opacity: 0,
            WebkitTransition:
              "-webkit-transform 0.2s ease-out, opacity 0.2s linear",
          });
          document.body.appendChild(this.backgroundElement);
          document.body.appendChild(this.domElement);
          var c = this;
          e.bind(this.backgroundElement, "click", function () {
            c.hide();
          });
        };
        c.prototype.show = function () {
          var c = this;
          this.backgroundElement.style.display = "block";
          this.domElement.style.display = "block";
          this.domElement.style.opacity = 0;
          this.domElement.style.webkitTransform = "scale(1.1)";
          this.layout();
          a.defer(function () {
            c.backgroundElement.style.opacity = 1;
            c.domElement.style.opacity = 1;
            c.domElement.style.webkitTransform = "scale(1)";
          });
        };
        c.prototype.hide = function () {
          var a = this,
            c = function () {
              a.domElement.style.display = "none";
              a.backgroundElement.style.display = "none";
              e.unbind(a.domElement, "webkitTransitionEnd", c);
              e.unbind(a.domElement, "transitionend", c);
              e.unbind(a.domElement, "oTransitionEnd", c);
            };
          e.bind(this.domElement, "webkitTransitionEnd", c);
          e.bind(this.domElement, "transitionend", c);
          e.bind(this.domElement, "oTransitionEnd", c);
          this.backgroundElement.style.opacity = 0;
          this.domElement.style.opacity = 0;
          this.domElement.style.webkitTransform = "scale(1.1)";
        };
        c.prototype.layout = function () {
          this.domElement.style.left =
            window.innerWidth / 2 - e.getWidth(this.domElement) / 2 + "px";
          this.domElement.style.top =
            window.innerHeight / 2 - e.getHeight(this.domElement) / 2 + "px";
        };
        return c;
      })(dat.dom.dom, dat.utils.common)),
      dat.dom.dom,
      dat.utils.common
    );
  </script>
  <script>
    /* Copyright (C) 2013 Justin Windle, http://soulwire.co.uk */
    !(function (e, t) {
      "object" == typeof exports
        ? (module.exports = t(e, e.document))
        : "function" == typeof define && define.amd
        ? define(function () {
            return t(e, e.document);
          })
        : (e.Sketch = t(e, e.document));
    })("undefined" != typeof window ? window : this, function (e, t) {
      "use strict";
      function n(e) {
        return "[object Array]" == Object.prototype.toString.call(e);
      }
      function o(e) {
        return "function" == typeof e;
      }
      function r(e) {
        return "number" == typeof e;
      }
      function i(e) {
        return "string" == typeof e;
      }
      function u(e) {
        return C[e] || String.fromCharCode(e);
      }
      function a(e, t, n) {
        for (var o in t) (!n && o in e) || (e[o] = t[o]);
        return e;
      }
      function c(e, t) {
        return function () {
          e.apply(t, arguments);
        };
      }
      function l(e) {
        var t = {};
        for (var n in e)
          "webkitMovementX" !== n &&
            "webkitMovementY" !== n &&
            (o(e[n]) ? (t[n] = c(e[n], e)) : (t[n] = e[n]));
        return t;
      }
      function s(e) {
        function t(t) {
          o(t) && t.apply(e, [].splice.call(arguments, 1));
        }
        function n(e) {
          for (_ = 0; _ < ee.length; _++)
            (B = ee[_]),
              i(B)
                ? S[(e ? "add" : "remove") + "EventListener"].call(S, B, N, !1)
                : o(B)
                ? (N = B)
                : (S = B);
        }
        function r() {
          I(A),
            (A = R(r)),
            K || (t(e.setup), (K = o(e.setup))),
            U || (t(e.resize), (U = o(e.resize))),
            e.running &&
              !q &&
              ((e.dt = (z = +new Date()) - e.now),
              (e.millis += e.dt),
              (e.now = z),
              t(e.update),
              Z &&
                (e.retina && (e.save(), e.autoclear && e.scale(V, V)),
                e.autoclear && e.clear()),
              t(e.draw),
              Z && e.retina && e.restore()),
            (q = ++q % e.interval);
        }
        function c() {
          (S = J ? e.style : e.canvas),
            (D = J ? "px" : ""),
            (Y = e.width),
            (j = e.height),
            e.fullscreen &&
              ((j = e.height = v.innerHeight), (Y = e.width = v.innerWidth)),
            e.retina &&
              Z &&
              V &&
              ((S.style.height = j + "px"),
              (S.style.width = Y + "px"),
              (Y *= V),
              (j *= V)),
            S.height !== j && (S.height = j + D),
            S.width !== Y && (S.width = Y + D),
            Z && !e.autoclear && e.retina && e.scale(V, V),
            K && t(e.resize);
        }
        function s(e, t) {
          return (
            (L = t.getBoundingClientRect()),
            (e.x = e.pageX - L.left - (v.scrollX || v.pageXOffset)),
            (e.y = e.pageY - L.top - (v.scrollY || v.pageYOffset)),
            e
          );
        }
        function f(t, n) {
          return (
            s(t, e.element),
            (n = n || {}),
            (n.ox = n.x || t.x),
            (n.oy = n.y || t.y),
            (n.x = t.x),
            (n.y = t.y),
            (n.dx = n.x - n.ox),
            (n.dy = n.y - n.oy),
            n
          );
        }
        function d(e) {
          if (
            (e.preventDefault(), (G = l(e)), (G.originalEvent = e), G.touches)
          )
            for (Q.length = G.touches.length, _ = 0; _ < G.touches.length; _++)
              Q[_] = f(G.touches[_], Q[_]);
          else (Q.length = 0), (Q[0] = f(G, $));
          return a($, Q[0], !0), G;
        }
        function p(n) {
          for (
            n = d(n),
              M = (X = ee.indexOf((W = n.type))) - 1,
              e.dragging =
                !!/down|start/.test(W) || (!/up|end/.test(W) && e.dragging);
            M;

          )
            i(ee[M]) ? t(e[ee[M--]], n) : i(ee[X]) ? t(e[ee[X++]], n) : (M = 0);
        }
        function g(n) {
          (F = n.keyCode),
            (H = "keyup" == n.type),
            (te[F] = te[u(F)] = !H),
            t(e[n.type], n);
        }
        function m(n) {
          e.autopause && ("blur" == n.type ? E : y)(), t(e[n.type], n);
        }
        function y() {
          (e.now = +new Date()), (e.running = !0);
        }
        function E() {
          e.running = !1;
        }
        function k() {
          (e.running ? E : y)();
        }
        function P() {
          Z && e.clearRect(0, 0, e.width * V, e.height * V);
        }
        function T() {
          (O = e.element.parentNode),
            (_ = b.indexOf(e)),
            O && O.removeChild(e.element),
            ~_ && b.splice(_, 1),
            n(!1),
            E();
        }
        var A,
          N,
          S,
          O,
          L,
          _,
          D,
          z,
          B,
          G,
          W,
          F,
          H,
          M,
          X,
          Y,
          j,
          q = 0,
          Q = [],
          U = !1,
          K = !1,
          V = v.devicePixelRatio || 1,
          J = e.type == w,
          Z = e.type == h,
          $ = {
            x: 0,
            y: 0,
            ox: 0,
            oy: 0,
            dx: 0,
            dy: 0,
          },
          ee = [
            e.eventTarget || e.element,
            p,
            "mousedown",
            "touchstart",
            p,
            "mousemove",
            "touchmove",
            p,
            "mouseup",
            "touchend",
            p,
            "click",
            p,
            "mouseout",
            p,
            "mouseover",
            x,
            g,
            "keydown",
            "keyup",
            v,
            m,
            "focus",
            "blur",
            c,
            "resize",
          ],
          te = {};
        for (F in C) te[C[F]] = !1;
        return (
          a(e, {
            touches: Q,
            mouse: $,
            keys: te,
            dragging: !1,
            running: !1,
            millis: 0,
            now: NaN,
            dt: NaN,
            destroy: T,
            toggle: k,
            clear: P,
            start: y,
            stop: E,
          }),
          b.push(e),
          e.autostart && y(),
          n(!0),
          c(),
          r(),
          e
        );
      }
      for (
        var f,
          d,
          p =
            "E LN10 LN2 LOG2E LOG10E PI SQRT1_2 SQRT2 abs acos asin atan ceil cos exp floor log round sin sqrt tan atan2 pow max min".split(
              " "
            ),
          g = "__hasSketch",
          m = Math,
          h = "canvas",
          y = "webgl",
          w = "dom",
          x = t,
          v = e,
          b = [],
          E = {
            fullscreen: !0,
            autostart: !0,
            autoclear: !0,
            autopause: !0,
            container: x.body,
            interval: 1,
            globals: !0,
            retina: !1,
            type: h,
          },
          C = {
            8: "BACKSPACE",
            9: "TAB",
            13: "ENTER",
            16: "SHIFT",
            27: "ESCAPE",
            32: "SPACE",
            37: "LEFT",
            38: "UP",
            39: "RIGHT",
            40: "DOWN",
          },
          k = {
            CANVAS: h,
            WEB_GL: y,
            WEBGL: y,
            DOM: w,
            instances: b,
            install: function (e) {
              if (!e[g]) {
                for (var t = 0; t < p.length; t++) e[p[t]] = m[p[t]];
                a(e, {
                  TWO_PI: 2 * m.PI,
                  HALF_PI: m.PI / 2,
                  QUARTER_PI: m.PI / 4,
                  random: function (e, t) {
                    return n(e)
                      ? e[~~(m.random() * e.length)]
                      : (r(t) || ((t = e || 1), (e = 0)),
                        e + m.random() * (t - e));
                  },
                  lerp: function (e, t, n) {
                    return e + n * (t - e);
                  },
                  map: function (e, t, n, o, r) {
                    return ((e - t) / (n - t)) * (r - o) + o;
                  },
                }),
                  (e[g] = !0);
              }
            },
            create: function (e) {
              return (
                (e = a(e || {}, E)),
                e.globals && k.install(self),
                (f = e.element =
                  e.element ||
                  x.createElement(e.type === w ? "div" : "canvas")),
                (d = e.context =
                  e.context ||
                  (function () {
                    switch (e.type) {
                      case h:
                        return f.getContext("2d", e);
                      case y:
                        return (
                          f.getContext("webgl", e) ||
                          f.getContext("experimental-webgl", e)
                        );
                      case w:
                        return (f.canvas = f);
                    }
                  })()),
                (e.container || x.body).appendChild(f),
                k.augment(d, e)
              );
            },
            augment: function (e, t) {
              return (
                (t = a(t || {}, E)),
                (t.element = e.canvas || e),
                (t.element.className += " sketch"),
                a(e, t, !0),
                s(e)
              );
            },
          },
          P = ["ms", "moz", "webkit", "o"],
          T = self,
          A = 0,
          N = "AnimationFrame",
          S = "request" + N,
          O = "cancel" + N,
          R = T[S],
          I = T[O],
          L = 0;
        L < P.length && !R;
        L++
      )
        (R = T[P[L] + "Request" + N]), (I = T[P[L] + "Cancel" + N]);
      return (
        (T[S] = R =
          R ||
          function (e) {
            var t = +new Date(),
              n = m.max(0, 16 - (t - A)),
              o = setTimeout(function () {
                e(t + n);
              }, n);
            return (A = t + n), o;
          }),
        (T[O] = I =
          I ||
          function (e) {
            clearTimeout(e);
          }),
        k
      );
    });
  </script>

  <body>
    <div id="gui"></div>
  </body>
  <script>
    var sketch = Sketch.create(),
      center = {
        x: sketch.width / 2,
        y: sketch.height / 2,
      },
      orbs = [],
      dt = 1,
      opt = {
        total: 0,
        count: 100,
        spacing: 2,
        speed: 65,
        scale: 1,
        jitterRadius: 0,
        jitterHue: 0,
        clearAlpha: 10,
        toggleOrbitals: true,
        orbitalAlpha: 100,
        toggleLight: true,
        lightAlpha: 5,
        clear: function () {
          sketch.clearRect(0, 0, sketch.width, sketch.height),
            (orbs.length = 0);
        },
      };

    var Orb = function (x, y) {
      var dx = x / opt.scale - center.x / opt.scale,
        dy = y / opt.scale - center.y / opt.scale;
      this.angle = atan2(dy, dx);
      this.lastAngle = this.angle;
      this.radius = sqrt(dx * dx + dy * dy);
      this.size = this.radius / 300 + 1;
      this.speed = (random(1, 10) / 300000) * this.radius + 0.015;
    };

    Orb.prototype.update = function () {
      this.lastAngle = this.angle;
      this.angle += this.speed * (opt.speed / 50) * dt;
      this.x = this.radius * cos(this.angle);
      this.y = this.radius * sin(this.angle);
    };

    Orb.prototype.render = function () {
      if (opt.toggleOrbitals) {
        var radius =
          opt.jitterRadius === 0
            ? this.radius
            : this.radius + random(-opt.jitterRadius, opt.jitterRadius);
        radius = opt.jitterRadius != 0 && radius < 0 ? 0.001 : radius;
        sketch.strokeStyle =
          "hsla( " +
          ((this.angle + 90) / (PI / 180) +
            random(-opt.jitterHue, opt.jitterHue)) +
          ", 100%, 50%, " +
          opt.orbitalAlpha / 100 +
          " )";
        sketch.lineWidth = this.size;
        sketch.beginPath();
        if (opt.speed >= 0) {
          sketch.arc(0, 0, radius, this.lastAngle, this.angle + 0.001, false);
        } else {
          sketch.arc(0, 0, radius, this.angle, this.lastAngle + 0.001, false);
        }
        sketch.stroke();
        sketch.closePath();
      }

      if (opt.toggleLight) {
        sketch.lineWidth = 0.5;
        sketch.strokeStyle =
          "hsla( " +
          ((this.angle + 90) / (PI / 180) +
            random(-opt.jitterHue, opt.jitterHue)) +
          ", 100%, 70%, " +
          opt.lightAlpha / 100 +
          " )";
        sketch.beginPath();
        sketch.moveTo(0, 0);
        sketch.lineTo(this.x, this.y);
        sketch.stroke();
      }
    };

    var createOrb = function (config) {
      var x = config && config.x ? config.x : sketch.mouse.x,
        y = config && config.y ? config.y : sketch.mouse.y;
      orbs.push(new Orb(x, y));
    };

    var turnOnMove = function () {
      sketch.mousemove = createOrb;
    };

    var turnOffMove = function () {
      sketch.mousemove = null;
    };

    sketch.mousedown = function () {
      createOrb();
      turnOnMove();
    };

    sketch.mouseup = turnOffMove;

    sketch.resize = function () {
      center.x = sketch.width / 2;
      center.y = sketch.height / 2;
      sketch.lineCap = "round";
    };

    sketch.setup = function () {
      while (opt.count--) {
        createOrb({
          x: random(sketch.width / 2 - 300, sketch.width / 2 + 300),
          y: random(sketch.height / 2 - 300, sketch.height / 2 + 300),
        });
      }
    };

    sketch.clear = function () {
      sketch.globalCompositeOperation = "destination-out";
      sketch.fillStyle = "rgba( 0, 0, 0 , " + opt.clearAlpha / 100 + " )";
      sketch.fillRect(0, 0, sketch.width, sketch.height);
      sketch.globalCompositeOperation = "lighter";
    };

    sketch.update = function () {
      dt = sketch.dt < 0.1 ? 0.1 : sketch.dt / 16;
      dt = dt > 5 ? 5 : dt;
      var i = orbs.length;
      opt.total = i;
      while (i--) {
        orbs[i].update();
      }
    };

    sketch.draw = function () {
      sketch.save();
      sketch.translate(center.x, center.y);
      sketch.scale(opt.scale, opt.scale);
      var i = orbs.length;
      while (i--) {
        orbs[i].render();
      }
      sketch.restore();
    };

    gui = new dat.GUI({ autoPlace: false });
    gui.add(opt, "total").name("Total Orbitals").listen();
    gui.add(opt, "speed").min(-300).max(300).step(1).name("Speed");
    gui.add(opt, "scale").min(0.5).max(5).step(0.001).name("Scale");
    gui
      .add(opt, "jitterRadius")
      .min(0)
      .max(5)
      .step(0.001)
      .name("Radius Jitter");
    gui.add(opt, "jitterHue").min(0).max(90).step(1).name("Hue Jitter");
    gui.add(opt, "clearAlpha").min(0).max(100).step(1).name("Clear Alpha");
    gui.add(opt, "toggleOrbitals").name("Toggle Orbitals");
    gui.add(opt, "orbitalAlpha").min(0).max(100).step(1).name("Orbital Alpha");
    gui.add(opt, "toggleLight").name("Toggle Light");
    gui.add(opt, "lightAlpha").min(0).max(100).step(1).name("Light Alpha");

    gui.add(opt, "clear").name("Clear");
    customContainer = document.getElementById("gui");
    customContainer.appendChild(gui.domElement);

    document.onselectstart = function () {
      return false;
    };
  </script>
</html>
